﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using StockFinder.Services.Engines;
using Db4objects.Db4o;
using StockFinder.Model;
using StockFinder.Model.Constants;
using Db4objects.Db4o.Config;
using StockFinder.DataAccess;
using StockFinder.NorgatePremiumData;
using System.IO;
using System.Data.SqlClient;
using StockFinder.Indicators.Day;
using StockFinder.Indicators.Day.Volume;
using StockFinder.Indicators.Day.ClosePrice;
using StockFinder.Indicators.Day.HighPrice;
using StockFinder.Indicators.Day.LowPrice;
using System.Diagnostics;

namespace Testharness
{
    public partial class PriceHistoryTester : Form
    {
        public PriceHistoryTester()
        {
            InitializeComponent();
        }
        
        private void button1_Click(object sender, EventArgs e)
        {
            //1 truncate symbols table
            SymbolDataAccess.TruncateSymbolTable();

            //2 truncate price data table
            DailyPriceDataAccess.TruncateDailyPriceTable();

            //3 extract price histories
            const string PARENT_DIRECTORY = @"C:\Data\PriceHistory\Norgate\";
            //const string PARENT_DIRECTORY = @"C:\Trading Data\Formatted Output\US\";
            string[] OFFLINE_DIRECTORYS = 
            { 
                "AMEX",
                "Delisted Securities",
                "NASDAQ",
                "NYSE",
                "NYSE Arca",
            };

            SqlConnection connection = new SqlConnection(ApplicationConfiguation.DatabaseConnectionString);
            connection.Open();

            SqlBulkCopy bulkCopy = new SqlBulkCopy(connection,
                        SqlBulkCopyOptions.TableLock | SqlBulkCopyOptions.UseInternalTransaction, null);

            DataTable priceDataTable = new DataTable("PriceData");
            priceDataTable.Columns.Add("SymbolId", typeof(int));
            priceDataTable.Columns.Add("Date", typeof(DateTime));
            priceDataTable.Columns.Add("Open", typeof(decimal));
            priceDataTable.Columns.Add("High", typeof(decimal));
            priceDataTable.Columns.Add("Low", typeof(decimal));
            priceDataTable.Columns.Add("Close", typeof(decimal));
            priceDataTable.Columns.Add("AdjustedOpen", typeof(decimal));
            priceDataTable.Columns.Add("AdjustedHigh", typeof(decimal));
            priceDataTable.Columns.Add("AdjustedLow", typeof(decimal));
            priceDataTable.Columns.Add("AdjustedClose", typeof(decimal));
            priceDataTable.Columns.Add("Volume", typeof(decimal));

            priceDataTable.Columns.Add("MovingAverage50", typeof(decimal));
            //priceDataTable.Columns.Add("PercentFromMovingAverage50", typeof(decimal));
            priceDataTable.Columns.Add("MovingAverage200", typeof(decimal));
            //priceDataTable.Columns.Add("PercentFromMovingAverage200", typeof(decimal));
            priceDataTable.Columns.Add("Atr20", typeof(decimal));
            priceDataTable.Columns.Add("AtrPercentClose20", typeof(decimal));
            priceDataTable.Columns.Add("AverageVolume22", typeof(decimal));
            priceDataTable.Columns.Add("PercentFromAverageVolume22", typeof(decimal));
            priceDataTable.Columns.Add("AverageVolume66", typeof(decimal));
            priceDataTable.Columns.Add("PercentFromAverageVolume66", typeof(decimal));
            priceDataTable.Columns.Add("High52Week", typeof(decimal));
            priceDataTable.Columns.Add("Low52Week", typeof(decimal));
            priceDataTable.Columns.Add("Rsi14", typeof(decimal));
            priceDataTable.Columns.Add("Rsi20", typeof(decimal));
            priceDataTable.Columns.Add("DonchianUpper10", typeof(decimal));
            priceDataTable.Columns.Add("DonchianUpper20", typeof(decimal));
            priceDataTable.Columns.Add("DonchianUpper55", typeof(decimal));
            priceDataTable.Columns.Add("DonchianLower10", typeof(decimal));
            priceDataTable.Columns.Add("DonchianLower20", typeof(decimal));
            priceDataTable.Columns.Add("DonchianLower55", typeof(decimal));

            bulkCopy.DestinationTableName = "PriceData";

            var indicators = new List<BaseDayIndicator>()
            {                
                new SimpleMovingAverageClosePriceDayIndicator(50, "MovingAverage50"),
                new SimpleMovingAverageClosePriceDayIndicator(200, "MovingAverage200"),                
                new ExponentialMovingAverageTrueRangeClosePriceDayIndicator(20, "Atr20"),
                new ExponentialMovingAverageTrueRangePercentOfClosePriceDayIndicator(20, "AtrPercentClose20"),
                new SimpleMovingAverageDailyVolumeDayIndicator(22, "AverageVolume22"),
                new SimpleMovingAveragePercentOfDailyVolumeDayIndicator(22, "PercentFromAverageVolume22"),
                new SimpleMovingAverageDailyVolumeDayIndicator(66, "AverageVolume66"),
                new SimpleMovingAveragePercentOfDailyVolumeDayIndicator(66, "PercentFromAverageVolume66"),
                new MaxHighPriceDayIndicator(252, "High52Week"),
                new MinLowPriceDayIndicator(252, "Low52Week"),
                new ExponentialMovingAverageWilderRelativeStrengthIndexClosePriceDayIndicator(14, "Rsi14"),
                new ExponentialMovingAverageWilderRelativeStrengthIndexClosePriceDayIndicator(20, "Rsi20"),
                new DonchianUpperChannelHighPriceDayIndicator(10, "DonchianUpper10"),
                new DonchianUpperChannelHighPriceDayIndicator(20, "DonchianUpper20"),
                new DonchianUpperChannelHighPriceDayIndicator(55, "DonchianUpper55"),
                new DonchianUpperChannelHighPriceDayIndicator(10, "DonchianLower10"),
                new DonchianUpperChannelHighPriceDayIndicator(20, "DonchianLower20"),
                new DonchianUpperChannelHighPriceDayIndicator(55, "DonchianLower55"),
            };
       
            var norgateExtractor = new NorgatePremiumDataStockFilePathsExtractor();

            foreach (var directory in OFFLINE_DIRECTORYS)
            {
                var directoryName = PARENT_DIRECTORY + directory;

                foreach (var priceHistoryFilename in Directory.EnumerateFiles(directoryName).ToList())
                {
                    var name = norgateExtractor.GetSymbolNameFromFileName(priceHistoryFilename) + "_" + directory;
                    System.Diagnostics.Debug.WriteLine(name);

                    var prices = norgateExtractor.GetStockPriceHistoryFromFilename(priceHistoryFilename);

                    priceDataTable.Rows.Clear();

                    int symbolId = SymbolDataAccess.InsertSymbol(name);

                    indicators.ForEach(ind => ind.ApplyIndicator(prices));

                    foreach (var pricedate in prices)
                    {
                        var row = priceDataTable.NewRow();
                        row["SymbolId"] = symbolId;
                        row["Date"] = pricedate.PriceDate;

                        //add normal price and vol
                        row["Open"] = pricedate.Open;
                        row["High"] = pricedate.High;
                        row["Low"] = pricedate.Low;
                        row["Close"] = pricedate.Close;
                        row["AdjustedOpen"] = pricedate.AdjustedOpen;
                        row["AdjustedHigh"] = pricedate.AdjustedHigh;
                        row["AdjustedLow"] = pricedate.AdjustedLow;
                        row["AdjustedClose"] = pricedate.AdjustedClose;
                        row["Volume"] = pricedate.Volume;

                        //get indiciator info
                        indicators.ForEach(ind => row[ind.IndicatorName] = pricedate.DayIndicators[ind.IndicatorName]);

                        priceDataTable.Rows.Add(row);
                    }

                    bulkCopy.WriteToServer(priceDataTable);

                    Debug.WriteLine(priceDataTable.Rows.Count);
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            PriceHistoryContainerUpdater updater = new PriceHistoryContainerUpdater();

            updater.Defrag();
        }

        private IEmbeddedConfiguration GeCreateIEmbeddedConfiguration()
        {
            IEmbeddedConfiguration config = Db4oEmbedded.NewConfiguration();
            config.Common.ActivationDepth = 1;
            //config.Common.ObjectClass(typeof(PriceHistoryContainer)).CascadeOnUpdate(true);
            //config.Common.ObjectClass(typeof(DailyPrice)).CascadeOnUpdate(true);
            //config.Common.ObjectClass(typeof(Symbol)).CascadeOnUpdate(true);

            return config;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            //1. get new instance of database
            using (IObjectContainer database = Db4oEmbedded.OpenFile(GeCreateIEmbeddedConfiguration(),
                ApplicationConfiguation.ObjectDatabaseSRootDirectory + "Test.yap"))
            {
                PriceHistoryContainer priceHistoryContainer = null;

                //get or create PriceHistoryContainer
                List<PriceHistoryContainer> priceHistoryContainers = database.Query<PriceHistoryContainer>().ToList();

                //PriceHistoryContainer doesnt exist so create it
                if (priceHistoryContainers == null || priceHistoryContainers.Count() == 0)
                {
                    priceHistoryContainer = new PriceHistoryContainer();
                    database.Store(priceHistoryContainer);
                }
                else
                {
                    //should only be 1 price history container
                    priceHistoryContainer = priceHistoryContainers[0];
                }                
            }

            //2. create dummy list

            using (IObjectContainer database = Db4oEmbedded.OpenFile(GeCreateIEmbeddedConfiguration(),
                ApplicationConfiguation.ObjectDatabaseSRootDirectory + "Test.yap"))
            {
                PriceHistoryContainer priceHistoryContainer = null;

                //get or create PriceHistoryContainer
                List<PriceHistoryContainer> priceHistoryContainers = database.Query<PriceHistoryContainer>().ToList();

                //PriceHistoryContainer doesnt exist so create it
                if (priceHistoryContainers == null || priceHistoryContainers.Count() == 0)
                {
                    priceHistoryContainer = new PriceHistoryContainer();
                }
                else
                {
                    //should only be 1 price history container
                    priceHistoryContainer = priceHistoryContainers[0];
                }

                database.Activate(priceHistoryContainer.Symbols, 2);

                for (int i = 10; i < 20; i++)
                {
                    priceHistoryContainer.Symbols.Add(new Symbol() { Name = i.ToString() });
                }                

                database.Store(priceHistoryContainer.Symbols);               
            }

            using (IObjectContainer database = Db4oEmbedded.OpenFile(GeCreateIEmbeddedConfiguration(),
                ApplicationConfiguation.ObjectDatabaseSRootDirectory + "Test.yap"))
            {
                PriceHistoryContainer priceHistoryContainer = null;

                //get or create PriceHistoryContainer
                List<PriceHistoryContainer> priceHistoryContainers = database.Query<PriceHistoryContainer>().ToList();

                //PriceHistoryContainer doesnt exist so create it
                if (priceHistoryContainers == null || priceHistoryContainers.Count() == 0)
                {
                    priceHistoryContainer = new PriceHistoryContainer();
                }
                else
                {
                    //should only be 1 price history container
                    priceHistoryContainer = priceHistoryContainers[0];
                }

                database.Activate(priceHistoryContainer.Symbols, 2);
            }
        }
    }
}
